﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace Janus.Cores.Configuration
{
    /// <summary>
    /// 配置文件管理
    /// </summary>
    public class ConfigManager:IDisposable
    {

        IConfigurationSource _config;
        private ConfigManager()
        {
            _config = ConfigurationSourceFactory.Create();
        }

        /// <summary>
        /// 默认的配置管理
        /// </summary>
        public static ConfigManager Default { get { return _lazy.Value; } }

        private ConfigManager( string fileName,bool refresh )
        {
            _config = new FileConfigurationSource(fileName, refresh );
        }

        /// <summary>
        /// 获取一个配置节
        /// </summary>
        /// <typeparam name="T">配置节类型<see cref="System.Configuration.ConfigurationSection"/></typeparam>
        /// <param name="sectionName">配置节名称</param>
        /// <returns>T类型的配置节实例</returns>
        public static T GetSection<T>(string sectionName) where T : ConfigurationElement
        {
            var section = (T)_lazy.Value.GetSection(sectionName);
            return section;
        }

        private static Lazy<ConfigManager> _lazy = new Lazy<ConfigManager>(() => new ConfigManager());

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <returns></returns>
        //public static ConfigManager Create()
        //{
        //    return new ConfigManager();
        //}

        /// <summary>
        /// 根据配置文件获取对应的配置管理
        /// </summary>
        /// <param name="fileName">配置文件全名称</param>
        /// <returns>配置管理</returns>
        public static ConfigManager Create(string fileName)
        {
            return new ConfigManager(fileName,false);
        }

        /// <summary>
        /// 根据配置文件获取对应的配置管理
        /// </summary>
        /// <param name="fileName">配置文件全名称</param>
        /// <param name="refresh">更新配置文件时是否通知</param>
        /// <returns>配置管理</returns>
        public static ConfigManager Create(string fileName,bool refresh)
        {
            return new ConfigManager(fileName, refresh);
        }        

        /// <summary>
        /// 获取配置节
        /// </summary>
        /// <param name="sectionName">配置节名称</param>
        /// <returns>配置节</returns>
        /// <example>
        /// <code>
        /// var config = ConfigManager.Create(@"mock.config");
        /// var section = config.GetSection("mockSection") as MockSection;
        /// Assert.IsNotNull(section);
        /// Assert.IsNotNull(section.Item);
        /// Assert.IsTrue(section.Item.Name == "A");
        /// </code>
        /// </example>
        public object GetSection(string sectionName)
        {
            return _config.GetSection(sectionName);
        }

        /// <summary>
        /// 添加一个配置节到配置文件中
        /// </summary>
        /// <param name="sectionName">节点名称</param>
        /// <param name="configurationSection">配置节</param>
        public void Add(string sectionName, System.Configuration.ConfigurationSection configurationSection)
        {
            _config.Add(sectionName, configurationSection);
        }

        /// <summary>
        /// 为配置节更新变化添加回调行为
        /// </summary>
        /// <param name="sectionName">配置节名称</param>
        /// <param name="action">回调行为，参数为配置节名称</param>
        public void AddSectionChangeHandler(string sectionName, Action<string> action)
        {
            _config.AddSectionChangeHandler(sectionName, (o, e) =>
                {
                    action(e.SectionName);
                });
        }
        
        /// <summary>
        /// 移除一个配置节
        /// </summary>
        /// <param name="sectionName">配置节名称</param>
        public void Remove(string sectionName)
        {
            _config.Remove(sectionName);
        }

        #region IDisposable Members

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            _config.Dispose();
        }

        #endregion
    }
}
